#!/usr/bin/env python3
"""
V22 Final Compositor — Concatenates 8 clips into final 60s video.
Adds subtitles, audio, transitions.
"""

import os
import subprocess
import textwrap
import shutil

BASE = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
CLIPS_DIR = os.path.join(BASE, "03_clips")
VIDEO_DIR = os.path.join(BASE, "04_video")
FFMPEG = "D:/AI_WORKSPACE/tools/ffmpeg/ffmpeg.exe"

os.makedirs(VIDEO_DIR, exist_ok=True)

# Clip sequence
CLIPS = [
    ("clip_01_hook.mp4", 8),
    ("clip_02_bad_csv.mp4", 7),
    ("clip_03_quality_gate.mp4", 8),
    ("clip_04_success.mp4", 6),
    ("clip_05_top20.mp4", 7),
    ("clip_06_compare.mp4", 7),
    ("clip_07_flow.mp4", 6),
    ("clip_08_decision.mp4", 6),
]

# Subtitles (SRT format) — timed to match each clip
SUBTITLES = [
    # Clip 1: Terminal failure (0-8s)
    (1, 300, 5000, "⚡ AI 管道抓取到 450 条候选数据，经过质量门禁时发现大量缺失字段"),
    (1, 5000, 7600, "❌ 17 条数据缺少 link 或 author，门禁分数 0.809 低于阈值 0.85，管道中止"),
    # Clip 2: Bad CSV (8-15s)
    (2, 300, 4000, "📋 原始 CSV 数据中，12 条记录缺少链接字段，5 条缺少作者字段"),
    (2, 4000, 6700, "🔴 空字段标红显示：数据源质量是管道运行的第一道关口"),
    # Clip 3: Quality gate code (15-23s)
    (3, 300, 4300, "🔧 质量门禁核心代码：REQUIRED_FIELDS 定义了必须字段"),
    (3, 4300, 7500, "📊 validate() 函数逐条检查，gate_score = passed/total 计算通过率"),
    # Clip 4: Terminal success (23-29s)
    (4, 300, 3500, "✅ 修复缺失字段后重新运行：全部 89 条通过质量门禁"),
    (4, 3500, 5800, "📈 数据丰富 → 智能评分 → TOP20 导出，全流程通过"),
    # Clip 5: TOP20 table (29-36s)
    (5, 300, 4000, "🏆 TOP20 排名出炉：互动分 + 价值分 = 总分，金/银/铜色标出前三"),
    (5, 4000, 6700, "🥇 Gaming Highlights 以 9.7 分夺冠，Dance Tutorial 9.3 分紧随其后"),
    # Clip 6: Compare (36-43s)
    (6, 300, 4000, "🔄 修复前后对比：左侧 17 条失败，右侧 0 条失败"),
    (6, 4000, 6700, "💡 Gate Score 从 0.809 提升到 1.000，关键就在数据补全"),
    # Clip 7: Pipeline flow (43-49s)
    (7, 300, 3500, "⚙️ 完整数据流水线：抓取 → 质量门禁 → 丰富 → 评分 → 导出"),
    (7, 3500, 5800, "🎯 质量门禁是整条管线的决策点：门禁不过 → 全部 SKIP"),
    # Clip 8: Decision (49-55s)
    (8, 300, 3500, "📋 工程复盘核心结论：不是抓不到数据，是门禁必须先修"),
    (8, 3500, 5800, "✅ 故障已修复，管道正常运行。数据质量前置检测是最高优先级"),
]


def generate_srt():
    """Generate SRT subtitle file from SUBTITLES list."""
    srt_path = os.path.join(VIDEO_DIR, "subtitles.srt")
    entries = []
    entry_num = 1
    cumulative = 0  # seconds offset for current clip

    for i, (clip_name, clip_dur) in enumerate(CLIPS):
        clip_idx = i + 1
        clip_subtitles = [s for s in SUBTITLES if s[0] == clip_idx]
        for _, start_ms, end_ms, text in clip_subtitles:
            abs_start = cumulative * 1000 + start_ms
            abs_end = cumulative * 1000 + end_ms
            s_start = f"{abs_start//3600000:02d}:{(abs_start%3600000)//60000:02d}:{(abs_start%60000)//1000:02d},{abs_start%1000:03d}"
            s_end = f"{abs_end//3600000:02d}:{(abs_end%3600000)//60000:02d}:{(abs_end%60000)//1000:02d},{abs_end%1000:03d}"
            entries.append(f"{entry_num}\n{s_start} --> {s_end}\n{text}\n")
            entry_num += 1
        cumulative += clip_dur

    with open(srt_path, "w", encoding="utf-8") as f:
        f.write("\n".join(entries))
    print(f"SRT generated: {srt_path} ({len(entries)} entries)")
    return srt_path


def generate_concat_file():
    """Generate ffmpeg concat demuxer file."""
    concat_path = os.path.join(VIDEO_DIR, "concat_list.txt")
    with open(concat_path, "w", encoding="utf-8") as f:
        for clip_name, _ in CLIPS:
            clip_path = os.path.join(CLIPS_DIR, clip_name).replace("\\", "/")
            f.write(f"file '{clip_path}'\n")
    print(f"Concat file: {concat_path}")
    return concat_path


def compose_final():
    """Compose final video with subtitles and audio."""
    # Generate intermediates
    srt_path = generate_srt()
    concat_path = generate_concat_file()

    # Step 1: Concatenate all clips without re-encoding
    concat_video = os.path.join(VIDEO_DIR, "v22_concatenated.mp4")
    cmd1 = [
        FFMPEG, "-y",
        "-f", "concat", "-safe", "0",
        "-i", concat_path,
        "-c", "copy",
        concat_video
    ]
    print("\n=== Step 1: Concatenating clips ===")
    subprocess.run(cmd1, check=True)
    print(f"Concatenated: {concat_video}")

    # Step 2: Check if audio is available and add subtitles
    voiceover = os.path.join(
        os.path.dirname(os.path.dirname(BASE)),
        "02_drafts", "voiceover.wav"
    )
    has_audio = os.path.exists(voiceover)

    final_video = os.path.join(VIDEO_DIR, "v22_screenshot_rebuild_60s.mp4")

    # Build subtitle filter — use relative path (no drive letter = no colon issue)
    srt_rel = "04_video/subtitles.srt"
    subtitle_filter = f"subtitles={srt_rel}:force_style='FontName=Microsoft YaHei,FontSize=22,PrimaryColr=&H00E6EDF3,OutlineColr=&H000D1117,BorderStyle=1,Outline=2,Shadow=0,MarginV=80'"

    print(f"  Subtitle filter: {subtitle_filter}")

    if has_audio:
        print(f"\n=== Step 2: Adding subtitles + audio ===")
        cmd2 = [
            FFMPEG, "-y",
            "-i", concat_video,
            "-i", voiceover,
            "-vf", subtitle_filter,
            "-c:v", "libx264", "-preset", "slow", "-crf", "20",
            "-c:a", "aac", "-b:a", "128k",
            "-pix_fmt", "yuv420p",
            "-shortest",
            final_video
        ]
    else:
        print(f"\n=== Step 2: Adding subtitles only ===")
        cmd2 = [
            FFMPEG, "-y",
            "-i", concat_video,
            "-vf", subtitle_filter,
            "-c:v", "libx264", "-preset", "slow", "-crf", "20",
            "-pix_fmt", "yuv420p",
            final_video
        ]

    subprocess.run(cmd2, check=True, cwd=BASE)
    print(f"\nFinal video: {final_video}")

    # Check result
    probe = subprocess.run(
        [FFMPEG.replace("ffmpeg", "ffprobe"), "-v", "error",
         "-show_entries", "format=duration,size",
         "-of", "default=noprint_wrappers=1", final_video],
        capture_output=True, text=True
    )
    print(f"Final video info: {probe.stdout}")

    # Clean up intermediate
    try:
        os.remove(concat_video)
    except:
        pass

    return final_video


def main():
    final_path = compose_final()
    size_mb = os.path.getsize(final_path) / (1024 * 1024)
    print(f"\n{'='*50}")
    print(f"🎬 FINAL VIDEO READY")
    print(f"   Path: {final_path}")
    print(f"   Size: {size_mb:.1f} MB")
    print(f"{'='*50}")


if __name__ == "__main__":
    main()
